package com.meilai.project.service.business.installOrder.impl;

import com.alibaba.fastjson.JSON;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.meilai.project.constant.InstallTypeEnum;
import com.meilai.project.controller.web.market.entity.BillMarketDetail;
import com.meilai.project.controller.web.market.service.BillMarketDetailService;
import com.meilai.project.dto.app.AppReplacePointDTO;
import com.meilai.project.dto.business.installOrder.*;
import com.meilai.project.dto.business.intentionScheme.BuildingPointVO;
import com.meilai.project.entity.business.building.BuildingArea;
import com.meilai.project.entity.business.installOrder.*;
import com.meilai.project.entity.business.sale.BillSale;
import com.meilai.project.entity.media.*;
import com.meilai.project.exception.CommonException;
import com.meilai.project.mapper.business.building.BuildingAreaMapper;
import com.meilai.project.mapper.business.installOrder.WorkOrderInstallDetailMapper;
import com.meilai.project.mapper.business.installOrder.WorkOrderInstallDetailPointMapper;
import com.meilai.project.mapper.business.installOrder.WorkOrderInstallDetailWorkerMapper;
import com.meilai.project.mapper.business.installOrder.WorkOrderMapper;
import com.meilai.project.mapper.business.media.MediaPointMapper;
import com.meilai.project.mapper.business.media.MediaTypeMapper;
import com.meilai.project.mapper.business.sale.BillSaleMapper;
import com.meilai.project.mapper.media.MediaPointChooseDaterangeMediapointMapper;
import com.meilai.project.service.business.installOrder.*;
import com.meilai.project.service.business.intentionScheme.PointProcessService;
import com.meilai.project.service.business.media.MediaTypeService;
import com.meilai.project.service.business.sale.BillSaleService;
import com.meilai.project.service.media.MediaPointChooseDaterangeMediapointReplaceLogService;
import com.meilai.project.service.media.MediaPointOccupySnapshotService;
import com.meilai.project.service.middleware.AttachmentService;
import com.meilai.project.util.FileUtil;
import com.meilai.project.util.ThreadLocalUserUtil;
import com.meilai.project.util.ppt.NewExportPPTUtil;
import com.meilai.project.vo.business.installOrder.*;
import com.meilai.project.vo.business.intentionScheme.PointProcessDateRangeVO;
import com.meilai.project.vo.business.intentionScheme.WorkerSubmitPhotoVO;
import lombok.extern.log4j.Log4j2;
import org.apache.commons.collections4.CollectionUtils;
import org.apache.commons.io.IOUtils;
import org.apache.commons.lang3.ArrayUtils;
import org.apache.poi.hssf.usermodel.*;
import org.apache.poi.ss.usermodel.HorizontalAlignment;
import org.apache.poi.ss.usermodel.IndexedColors;
import org.apache.poi.ss.usermodel.VerticalAlignment;
import org.apache.poi.ss.util.CellRangeAddress;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.mock.web.MockMultipartFile;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.multipart.MultipartFile;

import javax.servlet.http.HttpServletResponse;
import java.io.*;
import java.net.HttpURLConnection;
import java.net.URL;
import java.net.URLConnection;
import java.net.URLEncoder;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.util.*;
import java.util.stream.Collectors;
import java.util.zip.ZipEntry;
import java.util.zip.ZipOutputStream;


/**
 * @author ykb
 * @date 2022/3/17
 */
@Service
@Log4j2
public class WorkOrderServiceImpl extends ServiceImpl<WorkOrderMapper, WorkOrder> implements WorkOrderService {

    //设备图片临时存放目录
    private final String deviceImgTemPath = "deviceImgTemp";
    private final DateTimeFormatter dtf = DateTimeFormatter.ofPattern("yyyyMMddHHmmssSSS");
    @Autowired
    private BillSaleMapper billSaleMapper;
    @Autowired
    private BillSaleService billSaleService;
    @Autowired
    private BuildingAreaMapper buildingAreaMapper;
    @Autowired
    private MediaPointMapper mediaPointMapper;
    @Autowired
    private WorkOrderInstallDetailMapper workOrderInstallDetailMapper;
    @Autowired
    private WorkOrderInstallDetailWorkerMapper workOrderInstallDetailWorkerMapper;
    @Autowired
    private WorkOrderInstallDetailPointMapper workOrderInstallDetailPointMapper;
    @Autowired
    private MediaTypeMapper mediaTypeMapper;
    @Autowired
    private PointProcessService processService;
    @Autowired
    private NewExportPPTUtil newExportPPTUtil;
    @Autowired
    private AttachmentService attachmentService;
    @Autowired
    private WorkOrderInstallDetailService workOrderInstallDetailService;
    @Autowired
    private WorkOrderInstallDetailWorkerService workOrderInstallDetailWorkerService;
    @Autowired
    private WorkOrderInstallDetailPointService workOrderInstallDetailPointService;
    @Autowired
    private WorkerSubmitService workerSubmitService;
    @Autowired
    private MediaPointChooseDaterangeMediapointMapper mediaPointChooseDaterangeMediapointMapper;
    @Autowired
    private MediaPointOccupySnapshotService mediaPointOccupySnapshotService;
    @Autowired
    private MediaPointChooseDaterangeMediapointReplaceLogService mediaPointChooseDaterangeMediapointReplaceLogService;
    @Autowired
    private WorkerSubmitPhotoService workOrderSubmitPhotoService;
    @Autowired
    private MediaTypeService mediaTypeService;
    @Value("${spring.profiles.active}")
    private String evn;
    @Value("${static-resource.file-space}")
    private String FILE_SPACE;

    /**
     * 分页函数
     *
     * @param currentPage 当前页数
     * @param pageSize    每一页的数据条数
     * @param list        要进行分页的数据列表
     * @return 当前页要展示的数据
     */
    public static Page getPages(Integer currentPage, Integer pageSize, List list) {
        Page page = new Page();
        int size = list.size();

        if (pageSize > size) {
            pageSize = size;
        }

        // 求出最大页数，防止currentPage越界
        int maxPage = 0;
        if (size != 0) {
            maxPage = size % pageSize == 0 ? size / pageSize : size / pageSize + 1;
        }

        if (currentPage > maxPage) {
            currentPage = maxPage;
        }

        // 当前页第一条数据的下标
        int curIdx = currentPage > 1 ? (currentPage - 1) * pageSize : 0;

        List pageList = new ArrayList();

        // 将当前页的数据放进pageList
        for (int i = 0; i < pageSize && curIdx + i < size; i++) {
            pageList.add(list.get(curIdx + i));
        }

        page.setCurrent(currentPage).setSize(pageSize).setTotal(list.size()).setRecords(pageList);
        return page;
    }

    /**
     * 压缩文件夹的方法
     *
     * @param out
     * @param sourceFile
     * @param base       压缩后的文件路径
     */
    private static void compress(ZipOutputStream out, File sourceFile, String base) {
        FileInputStream fos = null;
        BufferedInputStream bis = null;
        try {
            //如果路径为目录（文件夹）
            if (sourceFile.isDirectory()) {
                //取出文件夹中的文件（或子文件夹）
                File[] flist = sourceFile.listFiles();
                if (flist.length == 0) {//如果文件夹为空，则只需在目的地zip文件中写入一个目录进入点
                } else {//如果文件夹不为空，则递归调用compress，文件夹中的每一个文件（或文件夹）进行压缩
                    for (int i = 0; i < flist.length; i++) {
                        compress(out, flist[i], base + "/" + flist[i].getName());
                    }
                }
            } else {//如果不是目录（文件夹），即为文件，则先写入目录进入点，之后将文件写入zip文件中
                out.putNextEntry(new ZipEntry(base));
                fos = new FileInputStream(sourceFile);
                bis = new BufferedInputStream(fos);
                int tag;
                //将源文件写入到zip文件中
                while ((tag = bis.read()) != -1) {
                    out.write(tag);
                }
                bis.close();
                fos.close();
            }
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            try {
                if (bis != null) bis.close();
                if (fos != null) fos.close();
            } catch (Exception e) {
                System.out.println(e.getMessage());
            }
        }
    }

    /**
     * 填充Excel
     *
     * @param data  数据
     * @param index 当前行
     */
    public static void fillExcel(WorkOrderPointDetailVO data, int index, HSSFSheet sheet, HSSFCellStyle textCenterCellStyle) {
        HSSFRow row = sheet.createRow(index);
        // 填充序号
        HSSFCell cell = row.createCell(0);
        cell.setCellValue(index - 1);
        cell.setCellStyle(textCenterCellStyle);

        HSSFCell cell1 = row.createCell(1);
        cell1.setCellValue(data.getBuilding_area_name());
        cell1.setCellStyle(textCenterCellStyle);

        HSSFCell cell2 = row.createCell(2);
        cell2.setCellValue(data.getMedia_type_name());
        cell2.setCellStyle(textCenterCellStyle);

        HSSFCell cell3 = row.createCell(3);
        cell3.setCellValue(data.getCode());
        cell3.setCellStyle(textCenterCellStyle);

        HSSFCell cell4 = row.createCell(4);
        cell4.setCellValue(data.getArea());
        cell4.setCellStyle(textCenterCellStyle);

        HSSFCell cell5 = row.createCell(5);
        cell5.setCellValue(data.getAddress());
        cell5.setCellStyle(textCenterCellStyle);

        HSSFCell cell6 = row.createCell(6);
        cell6.setCellValue(data.getBuilding_number());
        cell6.setCellStyle(textCenterCellStyle);

        HSSFCell cell7 = row.createCell(7);
        cell7.setCellValue(data.getUnit_number());
        cell7.setCellStyle(textCenterCellStyle);

        HSSFCell cell8 = row.createCell(8);
        cell8.setCellValue(data.getFloor());
        cell8.setCellStyle(textCenterCellStyle);

        HSSFCell cell9 = row.createCell(9);
        cell9.setCellValue(data.getCount());
        cell9.setCellStyle(textCenterCellStyle);

        HSSFCell cell10 = row.createCell(10);
        cell10.setCellValue(data.getSize());
        cell10.setCellStyle(textCenterCellStyle);

        HSSFCell cell11 = row.createCell(11);
        cell11.setCellValue(data.getMaterial());
        cell11.setCellStyle(textCenterCellStyle);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public boolean replacePoint(AppReplacePointDTO dto) {
        MediaPointChooseDaterangeMediapoint p = mediaPointChooseDaterangeMediapointMapper.getChoosePointByWorkOrderIdAndMediaPointId(dto.getWork_order_id(), dto.getOld_device_id());
        if (p == null) throw new CommonException("原设备不存在，请联系管理员！");
        WorkOrder wo = getById(dto.getWork_order_id());
        if (wo == null) throw new CommonException("工单不存在，请联系管理员！");
        if (!wo.getWork_order_type_id().equals(InstallTypeEnum.PUBLISH.getInstallType()))
            throw new CommonException("非上刊工单，无法调位！");
        Long billSaleId = wo.getBill_sale_id();
        if (billSaleId == null) throw new CommonException("数据异常，关联的销售单不存在，请联系管理员！");

        Long userId = ThreadLocalUserUtil.get().getId();
        LocalDateTime now = LocalDateTime.now();

        List<WorkOrder> wos = list(Wrappers.<WorkOrder>lambdaQuery().eq(WorkOrder::getBill_sale_id, billSaleId));
        // 与该销售单关联的工单ids
        List<Long> woIds = wos.stream().map(WorkOrder::getId).collect(Collectors.toList());

        // 替换点位
        MediaPointChooseDaterangeMediapoint temp = new MediaPointChooseDaterangeMediapoint();
        temp.setId(p.getId());
        temp.setMedia_point_id(dto.getNew_device_id());
        mediaPointChooseDaterangeMediapointMapper.updateById(temp);

        // 更新楼盘数据和工人数据
        MediaPoint oldP = mediaPointMapper.selectById(dto.getOld_device_id());
        MediaPoint newP = mediaPointMapper.selectById(dto.getNew_device_id());
        if (oldP == null || newP == null) throw new CommonException("设备不能存在，请联系管理员！");
        // 同一个旧楼盘下，其他点位的数量
        Integer oldOtherPC = mediaPointChooseDaterangeMediapointMapper.getOtherPointCount(p.getId(), oldP.getBuilding_area_id(), p.getDaterange_id());
        // 同一个新楼盘下，其他点位的数量
        Integer newOtherPC = mediaPointChooseDaterangeMediapointMapper.getOtherPointCount(p.getId(), newP.getBuilding_area_id(), p.getDaterange_id());

        List<WorkOrderInstallDetail> details = workOrderInstallDetailService.list(Wrappers.<WorkOrderInstallDetail>lambdaQuery().isNull(WorkOrderInstallDetail::getDeleted_at).in(WorkOrderInstallDetail::getWork_order_id, woIds).eq(WorkOrderInstallDetail::getBuilding_area_id, oldP.getBuilding_area_id()));
        if (CollectionUtils.isEmpty(details)) throw new CommonException("数据异常，请联系管理员！");
        Map<Integer, List<WorkOrderInstallDetail>> detailsCs = details.stream().collect(Collectors.groupingBy(WorkOrderInstallDetail::getWork_order_id, Collectors.toList()));
        boolean detailCError = false;
        for (List<WorkOrderInstallDetail> list : detailsCs.values()) {
            if (CollectionUtils.isEmpty(list) || list.size() != 1) { // 每个工单的该楼盘下，应该只有一条数据
                detailCError = true;
                break;
            }
        }
        if (detailCError) throw new CommonException("数据异常，请联系管理员！");

        List<WorkOrderInstallDetailWorker> workers = workOrderInstallDetailWorkerService.list(Wrappers.<WorkOrderInstallDetailWorker>lambdaQuery().isNull(WorkOrderInstallDetailWorker::getDeleted_at).in(WorkOrderInstallDetailWorker::getWork_order_id, woIds).eq(WorkOrderInstallDetailWorker::getBuilding_area_id, oldP.getBuilding_area_id()));
        Map<Integer, List<WorkOrderInstallDetailWorker>> workersMap = new HashMap<>();
        if (CollectionUtils.isNotEmpty(workers)) {
            workersMap = workers.stream().collect(Collectors.groupingBy(WorkOrderInstallDetailWorker::getWork_order_id, Collectors.toList()));
        }

        List<Long> removeDetailIds = new ArrayList<>();
        List<Long> removeWorkerRecordIds = new ArrayList<>();
        if (oldOtherPC == 0) {
            // 旧楼盘没有其他点位,删除旧楼盘和旧工人
            for (List<WorkOrderInstallDetail> list : detailsCs.values()) {
                removeDetailIds.addAll(list.stream().map(WorkOrderInstallDetail::getId).collect(Collectors.toList()));
            }
            for (List<WorkOrderInstallDetailWorker> list : workersMap.values()) {
                removeWorkerRecordIds.addAll(list.stream().map(WorkOrderInstallDetailWorker::getId).collect(Collectors.toList()));
            }
            workOrderInstallDetailService.removeByIds(removeDetailIds);
            workOrderInstallDetailWorkerService.removeByIds(removeWorkerRecordIds);
        }

        if (newOtherPC == 0) {
            // 新楼盘没有其他点位，需要新增detail和工人

            // 校验新楼盘无点位
            List<WorkOrderInstallDetail> newDetails = workOrderInstallDetailService.list(Wrappers.<WorkOrderInstallDetail>lambdaQuery().isNull(WorkOrderInstallDetail::getDeleted_at).in(WorkOrderInstallDetail::getWork_order_id, woIds).eq(WorkOrderInstallDetail::getBuilding_area_id, newP.getBuilding_area_id()));
            if (CollectionUtils.isNotEmpty(newDetails)) throw new CommonException("数据异常，请联系管理员！");

            if (CollectionUtils.isNotEmpty(woIds)) {
                List<WorkOrderInstallDetail> addDetails = (new HashSet<>(woIds)).stream().map(d -> {
                    WorkOrderInstallDetail newDetail = new WorkOrderInstallDetail();
                    newDetail.setWork_order_id(d.intValue());
                    newDetail.setBuilding_area_id(newP.getBuilding_area_id().intValue());
                    return newDetail;
                }).collect(Collectors.toList());
                if (CollectionUtils.isNotEmpty(addDetails)) {
                    workOrderInstallDetailService.saveBatch(addDetails);

                    List<WorkOrderInstallDetailWorker> newWorkers = new ArrayList<>();
                    for (WorkOrderInstallDetail addDetail : addDetails) {
                        List<WorkOrderInstallDetailWorker> toAddWorkers = workersMap.getOrDefault(addDetail.getWork_order_id(), new ArrayList<>());
                        if (CollectionUtils.isNotEmpty(toAddWorkers)) {
                            newWorkers.addAll(toAddWorkers.stream().map(d -> {
                                WorkOrderInstallDetailWorker newWorker = new WorkOrderInstallDetailWorker();
                                newWorker.setWork_order_install_detail_id(addDetail.getId().intValue());
                                newWorker.setWork_order_id(addDetail.getWork_order_id());
                                newWorker.setBuilding_area_id(newP.getBuilding_area_id().intValue());
                                newWorker.setWorker_id(d.getWorker_id());
                                return newWorker;
                            }).collect(Collectors.toList()));
                        }
                    }
                    if (CollectionUtils.isNotEmpty(newWorkers))
                        workOrderInstallDetailWorkerService.saveBatch(newWorkers);
                }
            }
        }


        // 插入替换历史
        MediaPointChooseDaterangeMediapointReplaceLog lo = new MediaPointChooseDaterangeMediapointReplaceLog();
        BeanUtils.copyProperties(p, lo);
        lo.setMedia_point_id(dto.getNew_device_id());
        lo.setOld_media_point_id(dto.getOld_device_id());
        lo.setChoose_point_auto_id(p.getId());
        lo.setReplace_at(now);
        lo.setOperator_id(userId);
        lo.setId(null);
        mediaPointChooseDaterangeMediapointReplaceLogService.save(lo);

        // 更新点位占用快照表
        List<MediaPointOccupySnapshot> snapshots = mediaPointOccupySnapshotService.list(new QueryWrapper<MediaPointOccupySnapshot>().eq("choose_id", p.getChoose_id()).eq("daterange_id", p.getDaterange_id()).eq("media_point_id", dto.getOld_device_id()));
        if (CollectionUtils.isNotEmpty(snapshots) && snapshots.size() == 1) {
            MediaPointOccupySnapshot s = new MediaPointOccupySnapshot();
            s.setId(snapshots.get(0).getId());
            s.setMedia_point_id(dto.getNew_device_id());
            mediaPointOccupySnapshotService.updateById(s);
        }

        return true;
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void submitRepairOrder(WorkerRepairPointDTO req) {
        //创建主表信息
        log.info("1、创建维修工单");
        WorkOrder workOrder = assembleRepairWorkOrder(req);
        baseMapper.insert(workOrder);
        Long workOrderId = workOrder.getId();
        req.setId(workOrderId);
        log.info("2、更新维修列表中的工单ID");
        workerSubmitService.updateRepairStatus(workOrderId, req.getWorkerSubmitIdList());
        log.info("3、生成维修工单安装详情表数据");
        List<WorkOrderInstallDetail> detailList = assembleInstallDetail(req);
        workOrderInstallDetailService.saveBatch(detailList);
        initWorkOrderInstallDetailId(req, detailList);
        log.info("4、");
        List<WorkOrderInstallDetailWorker> workerList = assembleWorkOrderInstallDetailWorkerList(req);
        workOrderInstallDetailWorkerService.saveBatch(workerList);
        log.info("5、");
        List<WorkOrderInstallDetailPoint> workOrderInstallDetailPoints = assembleWorkOrderInstallDetailPointList(req);
        workOrderInstallDetailPointService.saveBatch(workOrderInstallDetailPoints);
        log.info("6、");
    }

    private List<WorkOrderInstallDetailPoint> assembleWorkOrderInstallDetailPointList(WorkerRepairPointDTO req) {
        List<WorkOrderInstallDetailPoint> result = new ArrayList<>();
        for (WorkerRepairPointDetailDTO detailDTO : req.getRepairDetailList()) {
            for (WorkerRepairPointDetailDTO.RepairPointDTO pointDTO : detailDTO.getAllocationList()) {
                WorkOrderInstallDetailPoint point = new WorkOrderInstallDetailPoint();
                point.setMedia_point_id(pointDTO.getMedia_point_id().intValue());
                point.setMedia_type_id(pointDTO.getMedia_type_id());
                point.setWork_order_id(req.getId().intValue());
                point.setWork_order_install_detail_id(detailDTO.getDetail_id().intValue());
                point.setBuilding_area_id(detailDTO.getBuilding_area_id().intValue());
                result.add(point);
            }
        }
        return result;
    }

    private List<WorkOrderInstallDetailWorker> assembleWorkOrderInstallDetailWorkerList(WorkerRepairPointDTO req) {
        List<WorkOrderInstallDetailWorker> result = new ArrayList<>();
        for (WorkerRepairPointDetailDTO detailDTO : req.getRepairDetailList()) {
            for (Long workerId : detailDTO.getWorker_id_list()) {
                WorkOrderInstallDetailWorker worker = new WorkOrderInstallDetailWorker();
                worker.setWorker_id(workerId.intValue());
                worker.setWork_order_id(req.getId().intValue());
                worker.setWork_order_install_detail_id(detailDTO.getDetail_id().intValue());
                worker.setBuilding_area_id(detailDTO.getBuilding_area_id().intValue());
                result.add(worker);
            }
        }
        return result;
    }

    private void initWorkOrderInstallDetailId(WorkerRepairPointDTO req, List<WorkOrderInstallDetail> detailList) {
        Map<Integer, List<WorkOrderInstallDetail>> buildingId2IdMap = detailList.stream().collect(Collectors.groupingBy(WorkOrderInstallDetail::getBuilding_area_id));
        for (WorkerRepairPointDetailDTO workerRepairPointDetailDTO : req.getRepairDetailList()) {
            Long id = buildingId2IdMap.get(workerRepairPointDetailDTO.getBuilding_area_id().intValue()).get(0).getId();
            workerRepairPointDetailDTO.setDetail_id(id);
        }
    }

    private List<WorkOrderInstallDetail> assembleInstallDetail(WorkerRepairPointDTO req) {
        List<WorkOrderInstallDetail> result = new ArrayList<>();
        for (WorkerRepairPointDetailDTO workerRepairPointDetailDTO : req.getRepairDetailList()) {
            WorkOrderInstallDetail detail = new WorkOrderInstallDetail();
            detail.setWork_order_id(req.getId().intValue());
            detail.setBuilding_area_id(workerRepairPointDetailDTO.getBuilding_area_id().intValue());
            result.add(detail);
        }
        return result;
    }

    private WorkOrder assembleRepairWorkOrder(WorkerRepairPointDTO req) {
        WorkOrder workOrder = new WorkOrder();
        workOrder.setWork_order_type_id(5);
        workOrder.setName(req.getName());
        workOrder.setDeadline(req.getDeadline());
        workOrder.setRemark(req.getRemark());
        workOrder.setStatus(1);
        return workOrder;
    }

    @Override
    public List<WorkerVO> listWorker(WorkerDTO workerDTO) {
        return baseMapper.selectWorker(workerDTO);
    }

    @Override
    public List<WorkOrder> listByBillSaleId(Long billSaleId) {
        LambdaQueryWrapper<WorkOrder> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.eq(WorkOrder::getBill_sale_id, billSaleId);
        return baseMapper.selectList(queryWrapper);
    }

    @Override
    public Page<WorkOrderBillSaleVO> listPageBillSale(Integer current_page, Integer page_size, WorkOrderBillSaleDTO workOrderBillSaleDTO) {
        Page<WorkOrderBillSaleVO> page = new Page<>(current_page, page_size);
        List<WorkOrderBillSaleVO> list = billSaleMapper.selectPageListBillSaleForWorkorder(page, workOrderBillSaleDTO);
        //增加销售单已关联的工单信息
        if (CollectionUtils.isNotEmpty(list)) {
            List<WorkOrder> listWorkOrder = baseMapper.selectList(new QueryWrapper<WorkOrder>().isNotNull("bill_sale_id").isNull("deleted_at").eq("status", 1));
            if (CollectionUtils.isNotEmpty(listWorkOrder)) {
                Map<Long, List<WorkOrder>> workOrderMap = listWorkOrder.stream().collect(Collectors.groupingBy(WorkOrder::getBill_sale_id));
                for (WorkOrderBillSaleVO workOrderBillSaleVO : list) {
                    workOrderBillSaleVO.setWorkOrderList(workOrderMap.get(workOrderBillSaleVO.getId()));
                }
            }
        }

        return page.setRecords(list);
    }

    @Override
    public Page<WorkOrderBuildingVO> listPageBuilding(Integer current_page, Integer page_size, WorkOrderBuidingDTO workOrderBuidingDTO) {
        if (workOrderBuidingDTO == null) {
            return null;
        }
        List<WorkOrderBuildingVO> list = new ArrayList<>();
        if (workOrderBuidingDTO.getWork_order_type_id() == InstallTypeEnum.INSTALL.getInstallType()) {
            list = buildingAreaMapper.listPageBuildingForNewInstallWorkOrder(workOrderBuidingDTO);
        } else if (workOrderBuidingDTO.getWork_order_type_id() == InstallTypeEnum.CHECK.getInstallType()) {
            list = buildingAreaMapper.listPageBuildingForCheckWorkOrder(workOrderBuidingDTO);
        }

        List<WorkOrderBuildingVO> new_list = handleData(list, workOrderBuidingDTO.getWork_order_type_id());
        return getPages(current_page, page_size, new_list);
    }

    @Override
    public List<WorkOrderBuildingVO> listPageBuildingForCheckWorkOrder(WorkOrderBuidingDTO workOrderBuidingDTO) {
        List<WorkOrderBuildingVO> workOrderBuildingVOS = buildingAreaMapper.listPageBuildingForCheckWorkOrder(workOrderBuidingDTO);
        return this.handleData(workOrderBuildingVOS, InstallTypeEnum.CHECK.getInstallType());
    }

    //构造 项目-点位类型-数量 结构
    private List<WorkOrderBuildingVO> handleData(List<WorkOrderBuildingVO> list, Integer work_order_type_id) {
        List<WorkOrderBuildingVO> new_list = new ArrayList<>();
        if (CollectionUtils.isNotEmpty(list)) {
            //获取巡检楼盘对应的点位信息
            List<MediaPoint> listMediaPoint = mediaPointMapper.selectList(new QueryWrapper<MediaPoint>().isNull("deleted_at").eq("status", 1));
            Map<Long, List<MediaPoint>> pointListMap = listMediaPoint.stream().filter(mp -> null != mp.getBuilding_area_id()).collect(Collectors.groupingBy(MediaPoint::getBuilding_area_id));

            List<MediaType> mediaTypes = mediaTypeMapper.selectList(new QueryWrapper<>());
            Map<Long, List<MediaType>> mediaTypesMap = mediaTypes.stream().collect(Collectors.groupingBy(MediaType::getId));
            Map<Long, List<WorkOrderBuildingVO>> buildingListMap = list.stream().collect(Collectors.groupingBy(WorkOrderBuildingVO::getId));
            if (buildingListMap != null && buildingListMap.keySet() != null && buildingListMap.size() != 0) {
                for (Long building_area_id : buildingListMap.keySet()) {
                    WorkOrderBuildingVO new_workOrderBuildingVO = new WorkOrderBuildingVO();
                    List<WorkOrderBuildingVO> workOrderBuidingDetailVOS1 = buildingListMap.get(building_area_id);
                    new_workOrderBuildingVO.setId(workOrderBuidingDetailVOS1.get(0).getId());
                    new_workOrderBuildingVO.setName(workOrderBuidingDetailVOS1.get(0).getName());
                    List<WorkOrderMediaPointVO> media_point = new ArrayList<>();
                    new_workOrderBuildingVO.setMedia_point(media_point);
                    if (work_order_type_id == InstallTypeEnum.INSTALL.getInstallType()) {
                        //新安装点位信息
                        Map<Integer, List<WorkOrderBuildingVO>> newInstallPonitListMap = workOrderBuidingDetailVOS1.stream().filter(mp -> null != mp.getMedia_type_id()).collect(Collectors.groupingBy(WorkOrderBuildingVO::getMedia_type_id));
                        if (newInstallPonitListMap != null && newInstallPonitListMap.keySet() != null && newInstallPonitListMap.size() != 0) {
                            for (Integer media_type_id : newInstallPonitListMap.keySet()) {
                                WorkOrderBuildingVO new_workOrderBuidingDetailVO = newInstallPonitListMap.get(media_type_id).get(0);
                                Integer num = new_workOrderBuidingDetailVO.getUninstall_point_num();
                                List<MediaType> mediaTypes1 = mediaTypesMap.get(media_type_id.longValue());
                                String media_type_name = mediaTypes1.get(0).getName();
                                WorkOrderMediaPointVO pointVO = new WorkOrderMediaPointVO();
                                pointVO.setMedia_type_id(media_type_id);
                                pointVO.setName(media_type_name);
                                pointVO.setNum(num);
                                media_point.add(pointVO);
                            }
                        }
                    } else if (work_order_type_id == InstallTypeEnum.CHECK.getInstallType()) {

                        //巡检点位信息
                        if (pointListMap != null && pointListMap.keySet() != null && pointListMap.size() != 0) {
                            List<MediaPoint> mediaPoints = pointListMap.get(building_area_id);
                            if (CollectionUtils.isNotEmpty(mediaPoints)) {
                                Map<Long, List<MediaPoint>> checkPonitListMap = mediaPoints.stream().filter(mp -> null != mp.getMedia_type_id()).collect(Collectors.groupingBy(MediaPoint::getMedia_type_id));
                                if (checkPonitListMap != null && checkPonitListMap.keySet() != null && checkPonitListMap.size() != 0) {
                                    for (Long media_type_id : checkPonitListMap.keySet()) {
                                        List<MediaPoint> pointList = checkPonitListMap.get(media_type_id);
                                        List<Long> point_ids = new ArrayList<>();
                                        if (CollectionUtils.isNotEmpty(pointList)) {
                                            for (MediaPoint point : pointList) {
                                                point_ids.add(point.getId().longValue());
                                            }
                                        }
                                        List<MediaType> mediaTypes1 = mediaTypesMap.get(media_type_id.longValue());
                                        WorkOrderMediaPointVO pointVO = new WorkOrderMediaPointVO();
                                        pointVO.setMedia_type_id(media_type_id.intValue());
                                        pointVO.setName(mediaTypes1.get(0).getName());
                                        pointVO.setPoint_ids(point_ids);
                                        media_point.add(pointVO);
                                    }
                                }
                            }

                        }
                    }

                    new_list.add(new_workOrderBuildingVO);
                }
            }
        }
        return new_list;
    }

    @Override
    public List<WorkOrderBuildingMatchWorkerVO> listBuildingMatchWorker(List<String> buildingIds) {
        List<BuildingArea> listBuildingArea = buildingAreaMapper.selectBatchIds(buildingIds);
        return handleBuildingArea(listBuildingArea);
    }

    @Override
    public WorkOrderBuildingOfBillSaleVO listBuildingOfBillSale(Long bill_sale_id, Long choose_id, Long daterange_id) {
        WorkOrderBuildingOfBillSaleVO result = new WorkOrderBuildingOfBillSaleVO();
        List<BuildingArea> listBuildingArea = buildingAreaMapper.listBuildingOfBillSale(bill_sale_id);
        List<WorkOrderBuildingMatchWorkerVO> list = handleBuildingArea(listBuildingArea);
        //点位信息补充
        List<PointProcessDateRangeVO> pointProcessDateRangeVOList = processService.queryChooseDateRangeVOList(choose_id, daterange_id);
        result.setWorkOrderBuildingMatchWorkerVOs(list);
        result.setDateRangeVOList(pointProcessDateRangeVOList);
        return result;
    }

    @Override
    @Transactional
    public boolean saveWorkOrder(WorkOrderDTO dto) {
        if (dto == null) {
            return true;
        }
        WorkOrder workOrder = new WorkOrder();
        BeanUtils.copyProperties(dto, workOrder);
        int insert = baseMapper.insert(workOrder);
        if (insert < 1) {
            return false;
        }
        Long workOrderId = workOrder.getId();
        int work_order_id = workOrderId.intValue();
        List<WorkOrderBuidingSaveDTO> buidingSaveDTOS = dto.getBuidingSaveDTOS();
        if (CollectionUtils.isEmpty(buidingSaveDTOS)) {
            return true;
        }
        Long bill_sale_id = dto.getBill_sale_id();
        //抽出保存公共代码，保存其他内容
        return saveOrUpdateWorkOrderOther(work_order_id, bill_sale_id, buidingSaveDTOS);

    }

    private boolean saveOrUpdateWorkOrderOther(int work_order_id, Long bill_sale_id, List<WorkOrderBuidingSaveDTO> buidingSaveDTOS) {
        if (bill_sale_id != null) {
            //销售单转工单 上刊、下刊、巡检-销售单
            for (WorkOrderBuidingSaveDTO workOrderBuidingSaveDTO : buidingSaveDTOS) {
                //保存工单安装详情
                Integer building_area_id = workOrderBuidingSaveDTO.getId();
                WorkOrderInstallDetail workOrderInstallDetail = new WorkOrderInstallDetail();
                workOrderInstallDetail.setWork_order_id(work_order_id);
                workOrderInstallDetail.setBuilding_area_id(building_area_id);
                int insert1 = workOrderInstallDetailMapper.insert(workOrderInstallDetail);
                if (insert1 < 1) {
                    return false;
                }
                Long work_order_install_detail_id = workOrderInstallDetail.getId();
                //保存工人
                List<Integer> workerIds = workOrderBuidingSaveDTO.getWorkerIds();
                if (CollectionUtils.isNotEmpty(workerIds)) {
                    for (Integer worker_id : workerIds) {
                        WorkOrderInstallDetailWorker workOrderInstallDetailWorker = new WorkOrderInstallDetailWorker();
                        workOrderInstallDetailWorker.setWork_order_install_detail_id(work_order_install_detail_id.intValue());
                        workOrderInstallDetailWorker.setWorker_id(worker_id);
                        workOrderInstallDetailWorker.setWork_order_id(work_order_id);
                        workOrderInstallDetailWorker.setBuilding_area_id(building_area_id);
                        workOrderInstallDetailWorkerMapper.insert(workOrderInstallDetailWorker);
                    }

                }
            }
        } else {
            //按楼盘选择 新安装、巡检-楼盘
            for (WorkOrderBuidingSaveDTO workOrderBuidingSaveDTO : buidingSaveDTOS) {
                //保存工单安装详情
                Integer building_area_id = workOrderBuidingSaveDTO.getId();
                //新安装
                Map<String, Integer> new_install_mediaPoint = workOrderBuidingSaveDTO.getNew_install_mediaPoint();
                if (new_install_mediaPoint != null && new_install_mediaPoint.keySet() != null) {
                    List<String> media_type_list = new ArrayList<>(new_install_mediaPoint.keySet());
                    for (String media_type_id : media_type_list) {
                        WorkOrderInstallDetail workOrderInstallDetail = new WorkOrderInstallDetail();
                        workOrderInstallDetail.setWork_order_id(work_order_id);
                        workOrderInstallDetail.setBuilding_area_id(building_area_id);
                        workOrderInstallDetail.setMedia_type_id(Integer.parseInt(media_type_id));
                        workOrderInstallDetail.setNum(new_install_mediaPoint.get(media_type_id));
                        int insert1 = workOrderInstallDetailMapper.insert(workOrderInstallDetail);
                        if (insert1 < 1) {
                            return false;
                        }
                        Long work_order_install_detail_id = workOrderInstallDetail.getId();
                        //保存工人
                        saveWorker(workOrderBuidingSaveDTO, work_order_install_detail_id, work_order_id, building_area_id);
                    }
                }
                //巡检-楼盘
                Map<String, List<Integer>> check_mediaPoint = workOrderBuidingSaveDTO.getCheck_mediaPoint();
                if (check_mediaPoint != null && check_mediaPoint.keySet() != null) {
                    List<String> media_type_list = new ArrayList<>(check_mediaPoint.keySet());
                    for (String media_type_id : media_type_list) {
                        WorkOrderInstallDetail workOrderInstallDetail = new WorkOrderInstallDetail();
                        workOrderInstallDetail.setWork_order_id(work_order_id);
                        workOrderInstallDetail.setBuilding_area_id(building_area_id);
                        workOrderInstallDetail.setMedia_type_id(Integer.parseInt(media_type_id));
                        int insert1 = workOrderInstallDetailMapper.insert(workOrderInstallDetail);
                        if (insert1 < 1) {
                            return false;
                        }
                        Long work_order_install_detail_id = workOrderInstallDetail.getId();
                        //保存工人
                        saveWorker(workOrderBuidingSaveDTO, work_order_install_detail_id, work_order_id, building_area_id);
                        //保存点位
                        List<Integer> mediaPointIds = check_mediaPoint.get(media_type_id);
                        if (CollectionUtils.isNotEmpty(mediaPointIds)) {
                            for (Integer media_point_id : mediaPointIds) {
                                WorkOrderInstallDetailPoint workOrderInstallDetailPoint = new WorkOrderInstallDetailPoint();
                                workOrderInstallDetailPoint.setWork_order_install_detail_id(work_order_install_detail_id.intValue());
                                workOrderInstallDetailPoint.setMedia_point_id(media_point_id);
                                workOrderInstallDetailPoint.setWork_order_id(work_order_id);
                                workOrderInstallDetailPoint.setBuilding_area_id(building_area_id);
                                workOrderInstallDetailPoint.setMedia_type_id(Integer.parseInt(media_type_id));
                                workOrderInstallDetailPointMapper.insert(workOrderInstallDetailPoint);
                            }

                        }
                    }
                }

            }
        }
        return true;
    }

    /**
     * 更新工单截止时间
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public boolean updateWorkOrderDeadLine(WorkOrderUpdateDeadlineDTO dto) {
        if(dto == null) return true;
        if(dto.getId() == null) return true;
        if(dto.getDeadline() == null) return true;
        WorkOrder workOrder = new WorkOrder();
        BeanUtils.copyProperties(dto, workOrder);
        int update = baseMapper.updateById(workOrder);
        if (update < 1) {
            return false;
        }
        return true;
    }

    @Override
    @Transactional
    public boolean updateWorkOrder(WorkOrderDTO dto) {
        if (dto == null) {
            return true;
        }
        WorkOrder workOrder = new WorkOrder();
        BeanUtils.copyProperties(dto, workOrder);
        int update = baseMapper.updateById(workOrder);
        if (update < 1) {
            return false;
        }
        Long workOrderId = workOrder.getId();
        int work_order_id = workOrderId.intValue();
        List<WorkOrderBuidingSaveDTO> buidingSaveDTOS = dto.getBuidingSaveDTOS();
        if (CollectionUtils.isEmpty(buidingSaveDTOS)) {
            return true;
        }
        Long bill_sale_id = dto.getBill_sale_id();
        //编辑的时候可能更换点位，所以先删除楼盘其他内容
        deleteWorkOrderOther(work_order_id, bill_sale_id, buidingSaveDTOS);
        //抽出保存公共代码，保存其他内容
        return saveOrUpdateWorkOrderOther(work_order_id, bill_sale_id, buidingSaveDTOS);
    }

    private void deleteWorkOrderOther(int work_order_id, Long bill_sale_id, List<WorkOrderBuidingSaveDTO> buidingSaveDTOS) {
        if (CollectionUtils.isNotEmpty(buidingSaveDTOS)) {
            for (WorkOrderBuidingSaveDTO workOrderBuidingSaveDTO : buidingSaveDTOS) {
                //修改工单安装详情
                List<WorkOrderInstallDetail> listWorkOrderInstallDetail = workOrderInstallDetailMapper.selectList(new QueryWrapper<WorkOrderInstallDetail>().eq("work_order_id", work_order_id).eq("building_area_id", workOrderBuidingSaveDTO.getId()).isNull("deleted_at"));
                //先删除原安装详情
                if (CollectionUtils.isNotEmpty(listWorkOrderInstallDetail)) {
                    for (WorkOrderInstallDetail workOrderInstallDetail : listWorkOrderInstallDetail) {
                        Long work_order_install_detail_id = workOrderInstallDetail.getId();
                        //删除安装详情
                        workOrderInstallDetailMapper.deleteById(work_order_install_detail_id);
                        //删除关联点位
                        workOrderInstallDetailPointMapper.delete(new QueryWrapper<WorkOrderInstallDetailPoint>().eq("work_order_install_detail_id", work_order_install_detail_id));
                        //删除原关联工人
                        workOrderInstallDetailWorkerMapper.delete(new QueryWrapper<WorkOrderInstallDetailWorker>().eq("work_order_install_detail_id", work_order_install_detail_id));
                    }
                }
            }
        }
    }

    private void saveWorker(WorkOrderBuidingSaveDTO workOrderBuidingSaveDTO, Long work_order_install_detail_id, int work_order_id, Integer building_area_id) {
        //保存工人
        List<Integer> workerIds = workOrderBuidingSaveDTO.getWorkerIds();
        if (CollectionUtils.isNotEmpty(workerIds)) {
            for (Integer worker_id : workerIds) {
                WorkOrderInstallDetailWorker workOrderInstallDetailWorker = new WorkOrderInstallDetailWorker();
                workOrderInstallDetailWorker.setWork_order_install_detail_id(work_order_install_detail_id.intValue());
                workOrderInstallDetailWorker.setWorker_id(worker_id);
                workOrderInstallDetailWorker.setWork_order_id(work_order_id);
                workOrderInstallDetailWorker.setBuilding_area_id(building_area_id);
                workOrderInstallDetailWorkerMapper.insert(workOrderInstallDetailWorker);
            }

        }
    }

    @Override
    public Page<WorkOrderVO> selectPageList(Integer current_page, Integer page_size, WorkOrderSearchDTO searchDTO) {
        Page<WorkOrderVO> page = new Page<>(current_page, page_size);
        if (CollectionUtils.isNotEmpty(searchDTO.getMedia_type_ids())) {
            List<Long> workIdsByMediaTypeIds = baseMapper.getWorkIdsByMediaTypeIds(searchDTO.getMedia_type_ids());
            if (CollectionUtils.isEmpty(workIdsByMediaTypeIds)) {
                workIdsByMediaTypeIds.add(-1L);
            }
            searchDTO.setIds(workIdsByMediaTypeIds);
        } else {
            searchDTO.setIds(null);
        }
        List<WorkOrderVO> list = baseMapper.selectPageList(page, searchDTO);
        // 获取每个类型数据
        Map<Long, List<MediaType>> mediaTypeMap = mediaTypeService.list().stream().collect(Collectors.groupingBy(MediaType::getId));
        // 获取返回数据中的媒体类型数据
        List<Long> ids = list.stream().map(WorkOrderVO::getId).collect(Collectors.toList());
        Map<Long, List<WorkOrderMediaTypeVO>> mediaTypeNameMap = baseMapper.getWorkMediaTypeList(ids).stream().collect(Collectors.groupingBy(WorkOrderMediaTypeVO::getId));
        // 设置点位类型数据
        list.forEach(item -> {
            if (mediaTypeNameMap.containsKey(item.getId())) {
                List<WorkOrderMediaTypeVO> workOrderMediaTypeVOS = mediaTypeNameMap.get(item.getId());
                Set<String> media_type_name_set = new HashSet<>();
                workOrderMediaTypeVOS.forEach(tmp -> {
                    if (mediaTypeMap.containsKey(tmp.getMedia_type_id())) {
                        media_type_name_set.add(mediaTypeMap.get(tmp.getMedia_type_id()).get(0).getName());
                    } else {
                        media_type_name_set.add("");
                    }
                });
                item.setMedia_type_name_list(new ArrayList<>(media_type_name_set));
            } else {
                item.setMedia_type_name_list(new ArrayList<>());
            }
        });
        return page.setRecords(list);
    }

    @Override
    public boolean delete(Long id) {
        LocalDateTime now = LocalDateTime.now();
        WorkOrder temp = getById(id);
        if (temp == null) return false;
        WorkOrder workOrder = new WorkOrder();
        workOrder.setId(id);
        workOrder.setDeleted_at(now);
        return updateById(workOrder);
    }

    @Override
    public boolean handClosed(Long id) {
        WorkOrder temp = getById(id);
        if (temp == null) return false;
        WorkOrder workOrder = new WorkOrder();
        workOrder.setId(id);
        workOrder.setHand_closed(true);
        return updateById(workOrder);
    }

    @Override
    public void genWorkOrderReport(String tenantName, WorkOrderReportInfoDTO data) {
        DateTimeFormatter dtf2 = DateTimeFormatter.ofPattern("yyyy年MM月dd日");
        boolean needCompress = true; // 是否压缩

        WorkOrder wo = new WorkOrder();
        wo.setId(data.getId());
        wo.setReport_can_download(0);
        wo.setReport_path("");
        baseMapper.updateById(wo);

        data.setCreate_time(dtf2.format(LocalDateTime.now()));
        log.info("生成步骤1：");
        data.setCount(baseMapper.getWorkOrderPassedNum(data.getId()));
        log.info("生成步骤2：");
        handleReportBuildingVO(data, baseMapper.getWorkOrderReportBuildingVOs(data.getId()));
        log.info("生成步骤3：");
        handleReportPointPhotoVO(data, baseMapper.getPointPhotos(data.getId(), data.getPer_device_one_photo()));
        log.info("生成步骤4：");
        //保存原图
        /**List<String> img_origin_list = data.getImg_origin_list();
         List<PictorialOriginImage> collect = img_origin_list.stream().map(
         item -> {
         PictorialOriginImage pictorialOriginImage = new PictorialOriginImage();
         pictorialOriginImage.setOrigin_image(item);
         pictorialOriginImage.setWork_order_id(data.getId());
         return pictorialOriginImage;
         }
         ).collect(Collectors.toList());
         pictorialOriginImageMapper.delete(Wrappers.<PictorialOriginImage>lambdaQuery().eq(PictorialOriginImage::getWork_order_id, data.getId()));
         for (PictorialOriginImage p : collect) {
         pictorialOriginImageMapper.insert(p);
         }*/
        String fileName = data.getFile_name() + "_" + dtf.format(LocalDateTime.now()) + ".pptx";
        log.info("生成报告数参数，{}", JSON.toJSONString(data));
        String localPath = "";
        if (data.getReport_type() == 1) {
            localPath = newExportPPTUtil.genWorkOrderReport(data, FILE_SPACE + File.separator + "ppt_mother_01.pptx", FILE_SPACE, fileName);
        } else {
            localPath = newExportPPTUtil.genWorkOrderReport2(data, FILE_SPACE + File.separator + "ppt_mother_01.pptx", FILE_SPACE, fileName);
        }
        log.info("ppt已保存至本地" + localPath);
        //如果是在生产环境，则压缩至zip，然后上传至oss，然后将本地文件删除
        if (evn.equals("prod")) {
            log.info("生产环境");
            File pptFile = new File(localPath);
            List<File> list = new ArrayList<>();
            list.add(pptFile);
            String tmpZipFilePath = "";
            String url = "";

            log.info("判断是否压缩");
            try {
                MultipartFile multipartFile = null;
                if (needCompress) {
                    log.info("压缩");
                    tmpZipFilePath = FileUtil.zipFile(list, fileName);
                    File tempZipfile = new File(tmpZipFilePath);
                    FileInputStream input = new FileInputStream(tempZipfile);
                    multipartFile = new MockMultipartFile("file", tempZipfile.getName(), "application/x-zip-compressed", IOUtils.toByteArray(input));
                    url = attachmentService.store2(tenantName, multipartFile.getInputStream(), multipartFile.getSize(), multipartFile.getContentType(), fileName + ".zip");
                    FileUtil.delFile(tmpZipFilePath);
                    log.info("zip已上传至oss," + url);
                } else {
                    log.info("不压缩");
                    FileInputStream input = new FileInputStream(pptFile);
                    multipartFile = new MockMultipartFile("file", pptFile.getName(), "application/vnd.openxmlformats-officedocument.presentationml.template", IOUtils.toByteArray(input));
                    url = attachmentService.store2(tenantName, multipartFile.getInputStream(), multipartFile.getSize(), multipartFile.getContentType(), fileName + ".pptx");
                    log.info("pptx已上传至oss," + url);
                }
                wo.setReport_can_download(1);
                wo.setReport_path(url);
                baseMapper.updateById(wo);
                log.info("上传完成");
            } catch (Exception e) {
                log.info("出错");
                e.printStackTrace();
                log.error(e);
            }
            try {
                FileUtil.delFile(localPath);
            } catch (Exception e) {
                e.printStackTrace();
                log.error(e);
            }
        } else {
            log.info("开发环境");
            //如果是在开发环境，则不上传至oss，本地文件不删除
            wo.setReport_can_download(1);
            wo.setReport_path(localPath);
            baseMapper.updateById(wo);
        }
    }

    private List<WorkOrderBuildingMatchWorkerVO> handleBuildingArea(List<BuildingArea> listBuildingArea) {
        Map<String, List<BuildingArea>> buildingAreaMap = listBuildingArea.stream().filter(mp -> null != mp.getAdcode()).collect(Collectors.groupingBy(BuildingArea::getAdcode));
        //List<MediaPoint> listMediaPoint = mediaPointMapper.selectList(new QueryWrapper<MediaPoint>().isNull("deleted_at").eq("status",1));
        //Map<Long, List<MediaPoint>> pointListMap = listMediaPoint.stream().filter(mp -> null != mp.getBuilding_area_id()).collect(Collectors.groupingBy(MediaPoint::getBuilding_area_id));

        List<String> adcodeList = new ArrayList<>(buildingAreaMap.keySet());
        List<WorkOrderBuildingMatchWorkerVO> workOrderBuildingMatchWorkerVOList = new ArrayList<>();
        for (String adcode : adcodeList) {
            WorkOrderBuildingMatchWorkerVO workOrderBuildingMatchWorkerVO = new WorkOrderBuildingMatchWorkerVO();
            workOrderBuildingMatchWorkerVO.setAdcode(adcode);
            List<BuildingArea> list = buildingAreaMap.get(adcode);
            if (CollectionUtils.isNotEmpty(list)) {
                BuildingArea buildingArea = list.get(0);
                String province = buildingArea.getProvince();
                String city = buildingArea.getCity();
                String area = buildingArea.getArea();
                workOrderBuildingMatchWorkerVO.setProvince(province);
                workOrderBuildingMatchWorkerVO.setCity(city);
                workOrderBuildingMatchWorkerVO.setArea(area);
                workOrderBuildingMatchWorkerVO.setBuildingAreaList(list);
                workOrderBuildingMatchWorkerVOList.add(workOrderBuildingMatchWorkerVO);
            }


        }
        return workOrderBuildingMatchWorkerVOList;
    }

    private void handleReportBuildingVO(WorkOrderReportInfoDTO dto, List<WorkOrderReportDetailByBuildingVO> list) {
        List<WorkOrderReportDetailByBuildingVO> resultList = new ArrayList<>();
        TreeMap<Long, String> pointTypeIdMap = new TreeMap<Long, String>();
        if (CollectionUtils.isNotEmpty(list)) {
            list.forEach(item -> {
                Long point_type_id = item.getPoint_type_id();
                pointTypeIdMap.putIfAbsent(point_type_id, item.getPoint_type());
            });
            if (pointTypeIdMap.size() == 1) {
                resultList = list.stream().peek(item -> {
                    Map<Long, WorkOrderReportDetailByBuildingInnerVO> counts = new HashMap<>();
                    counts.put(item.getPoint_type_id(), new WorkOrderReportDetailByBuildingInnerVO(item.getPoint_type(), (item.getCount() == 0 ? "" : item.getCount().toString())));
                    item.setCounts(counts);
                }).collect(Collectors.toList());
            } else if (pointTypeIdMap.size() > 1) {
                Map<String, WorkOrderReportDetailByBuildingVO> voMap = new TreeMap<>();
                list.forEach(item -> {
                    String key = item.getDaterange() + "_" + item.getBuilding_area_id();
                    WorkOrderReportDetailByBuildingVO temp = null;
                    if (voMap.get(key) == null) {
                        Map<Long, WorkOrderReportDetailByBuildingInnerVO> counts = new HashMap<>();
                        counts.put(item.getPoint_type_id(), new WorkOrderReportDetailByBuildingInnerVO(item.getPoint_type(), (item.getCount() == 0 ? "" : item.getCount().toString())));
                        temp = new WorkOrderReportDetailByBuildingVO();
                        BeanUtils.copyProperties(item, temp);
                        temp.setCounts(counts);
                    } else {
                        temp = voMap.get(key);
                        temp.getCounts().put(item.getPoint_type_id(), new WorkOrderReportDetailByBuildingInnerVO(item.getPoint_type(), (item.getCount() == 0 ? "" : item.getCount().toString())));
                    }
                    voMap.put(key, temp);
                });
                //这里将map.entrySet()转换成list
                List<Map.Entry<String, WorkOrderReportDetailByBuildingVO>> tempList = new ArrayList<Map.Entry<String, WorkOrderReportDetailByBuildingVO>>(voMap.entrySet());
                //然后通过比较器来实现排序
                tempList.sort(new Comparator<Map.Entry<String, WorkOrderReportDetailByBuildingVO>>() {
                    @Override
                    public int compare(Map.Entry<String, WorkOrderReportDetailByBuildingVO> o1, Map.Entry<String, WorkOrderReportDetailByBuildingVO> o2) {
                        return o1.getValue().getBuilding_area_id().compareTo(o2.getValue().getBuilding_area_id());
                    }
                });
                for (Map.Entry<String, WorkOrderReportDetailByBuildingVO> mapping : tempList) {
                    resultList.add(mapping.getValue());
                }
            }
        }

        String[] bHeaders = dto.getBuildingTableHeader();
        String[] temp = new String[pointTypeIdMap.size()];
        int k = 0;
        for (String value : pointTypeIdMap.values()) {
            temp[k] = value;
            k++;
        }
        dto.setBuildingTableHeader(ArrayUtils.addAll(bHeaders, temp));
        if (CollectionUtils.isNotEmpty(resultList)) {
            String[][] bDatas = new String[resultList.size()][4 + pointTypeIdMap.size()];
            for (int i = 0; i < resultList.size(); i++) {
                WorkOrderReportDetailByBuildingVO item = resultList.get(i);
                String[] row = {Integer.toString(i + 1), item.getBuilding_area(), item.getBuilding_area_address(), item.getDaterange()};
                String[] rowCount = new String[pointTypeIdMap.size()];
                Map<Long, WorkOrderReportDetailByBuildingInnerVO> counts = item.getCounts();
                if (counts != null && counts.size() > 0) {
                    int m = 0;
                    for (Long key : pointTypeIdMap.keySet()) {
                        rowCount[m] = (counts.get(key) != null && counts.get(key).getCount() != null) ? counts.get(key).getCount().toString() : "";
                        m++;
                    }
                }
                bDatas[i] = ArrayUtils.addAll(row, rowCount);
            }
            dto.setBuildingTableData(bDatas);
        } else {
            dto.setBuildingTableData(null);
        }

    }

    private void handleReportPointPhotoVO(WorkOrderReportInfoDTO dto, List<WorkOrderReportPhotoVO> originList) {
        if (CollectionUtils.isNotEmpty(originList)) {
            List<WorkOrderReportPhotoReformVO> resultList = new ArrayList<>();
            TreeMap<Long, WorkOrderReportPhotoReformVO> buildingMap = new TreeMap<>();
            HashMap<Long, List<WorkOrderReportPhotoReformDateRangeVO>> daterangeMap = new HashMap<>();
            HashMap<String, List<WorkOrderReportPhotoReformInnerVO>> pointMap = new HashMap<>();
            HashMap<Long, Set<String>> pointCountMap = new HashMap<>();

            for (WorkOrderReportPhotoVO item : originList) {
                Long key = item.getBuilding_area_id();
                if (key == null) continue;

                // 楼盘信息
                WorkOrderReportPhotoReformVO building = new WorkOrderReportPhotoReformVO();
                BeanUtils.copyProperties(item, building);
                building.getDateranges().add(building.getDaterange());
                buildingMap.putIfAbsent(key, building);

                // 时间段信息
                if (CollectionUtils.isNotEmpty(building.getDateranges())) {
                    for (String daterange : building.getDateranges()) {
                        List<WorkOrderReportPhotoReformDateRangeVO> daterangeSet = daterangeMap.get(key);
                        if (daterangeSet == null) {
                            daterangeSet = new ArrayList<>();
                        }
                        boolean isExist = false;
                        for (WorkOrderReportPhotoReformDateRangeVO vo : daterangeSet) {
                            if (vo.getDaterange().equals(daterange)) {
                                isExist = true;
                                break;
                            }
                        }
                        if (!isExist) {
                            WorkOrderReportPhotoReformDateRangeVO dateRangeVO = new WorkOrderReportPhotoReformDateRangeVO();
                            dateRangeVO.setBuilding_area_id(key);
                            dateRangeVO.setDaterange(daterange);
                            daterangeSet.add(dateRangeVO);
                        }
                        daterangeMap.putIfAbsent(key, daterangeSet);
                    }
                }

                // 点位信息
                String key2 = key + "_" + building.getDaterange();
                List<WorkOrderReportPhotoReformInnerVO> points = pointMap.get(key2);
                if (points == null) {
                    points = new ArrayList<>();
                }
                WorkOrderReportPhotoReformInnerVO point = new WorkOrderReportPhotoReformInnerVO();
                BeanUtils.copyProperties(item, point);
                points.add(point);
                pointMap.put(key2, points);

                // 点位数量
                Set<String> pointCounts = pointCountMap.get(key);
                if (pointCounts == null) {
                    pointCounts = new HashSet<String>();
                }
                pointCounts.add(item.getId().toString());
                pointCountMap.putIfAbsent(key, pointCounts);
            }

            int pointIdx = 0;
            Long prevBuildingAreaId = 0L;
            Long prevPointAuditId = 0L;
            if (buildingMap.size() > 0) {
                for (Map.Entry<Long, WorkOrderReportPhotoReformVO> mapping : buildingMap.entrySet()) {
                    WorkOrderReportPhotoReformVO curBuild = mapping.getValue();
                    List<WorkOrderReportPhotoReformDateRangeVO> daterangeSet = daterangeMap.get(mapping.getKey());
                    if (CollectionUtils.isNotEmpty(daterangeSet)) {
                        for (WorkOrderReportPhotoReformDateRangeVO daterangevo : daterangeSet) {
                            String key2 = mapping.getKey() + "_" + daterangevo.getDaterange();
                            List<WorkOrderReportPhotoReformInnerVO> curPoints = pointMap.get(key2);
                            if (CollectionUtils.isNotEmpty(curPoints)) {
                                curPoints.sort((WorkOrderReportPhotoReformInnerVO b1, WorkOrderReportPhotoReformInnerVO b2) -> b2.getId().compareTo(b1.getId()));
                                for (WorkOrderReportPhotoReformInnerVO p : curPoints) {
                                    if (!p.getBuilding_area_id().equals(prevBuildingAreaId)) {
                                        prevBuildingAreaId = p.getBuilding_area_id();
                                        pointIdx = 0;
                                    }
                                    if (!p.getId().equals(prevPointAuditId)) {
                                        prevPointAuditId = p.getId();
                                        pointIdx++;
                                    }
                                    p.setIdx(String.valueOf(pointIdx));
                                }
                                daterangevo.setPoints(curPoints);
                            }
                        }
                        curBuild.setDaterangeVOs(daterangeSet);
                    }
                    Set<String> countSet = pointCountMap.get(mapping.getKey());
                    curBuild.setCount(countSet.size());
                    resultList.add(curBuild);
                }
            }
            dto.setPhotos(resultList.size() > 0 ? resultList : new ArrayList<>());
        }
    }

    @Autowired
    private BillMarketDetailService marketDetailService;

    @Override
    public WorkOrderDetailVO getWorkOrderDetailById(Long id) {
        WorkOrder workOrder = getById(id);
        WorkOrderDetailVO workOrderDetailVO = new WorkOrderDetailVO();
        BeanUtils.copyProperties(workOrder, workOrderDetailVO);

        //点位信息补充
        List<PointProcessDateRangeVO> pointProcessDateRangeVOList = new ArrayList<>();
        //获取当前销售单
        Long bill_sale_id = workOrder.getBill_sale_id();
        if (bill_sale_id != null) {
            if (bill_sale_id < 765){
                BillSale billSale = billSaleService.getById(bill_sale_id);
                Long choose_id = billSale.getChoose_id();
                Long daterange_id = billSale.getDaterange_id();
                pointProcessDateRangeVOList = processService.queryChooseDateRangeVOList(choose_id, daterange_id);
            }else {
                BillMarketDetail marketDetail = marketDetailService.getById(workOrder.getBill_market_detail_id());
                Long choose_id = marketDetail.getChoose_id();
                Long daterange_id = marketDetail.getDaterange_id();
                pointProcessDateRangeVOList = processService.queryChooseDateRangeVOList(choose_id, daterange_id);
            }
            workOrderDetailVO.setDateRangeVOList(pointProcessDateRangeVOList);
        }

        Integer work_order_type_id = workOrder.getWork_order_type_id();
        List<WorkOrderBuidingDetailVO> buidingDetailVOS = new ArrayList<>();
        List<MediaType> mediaTypes = mediaTypeMapper.selectList(new QueryWrapper<>());
        Map<Long, List<MediaType>> mediaTypesMap = mediaTypes.stream().collect(Collectors.groupingBy(MediaType::getId));

        List<WorkOrderBuidingDetailVO> workOrderBuidingDetailVOS = workOrderInstallDetailMapper.listWorkOrderBuildingByWorkOrderId(id);
        List<WorkOrderInstallDetailPoint> workOrderInstallDetailPointList = workOrderInstallDetailPointMapper.selectList(new QueryWrapper<WorkOrderInstallDetailPoint>().isNull("deleted_at").eq("work_order_id", id));
        List<WorkerDTO> workers = workOrderInstallDetailWorkerMapper.listWorkOrderBuildingWorkByWorkOrderId(id);
        Map<Integer, List<WorkOrderInstallDetailPoint>> buildingPointListMap = workOrderInstallDetailPointList.stream().filter(mp -> null != mp.getBuilding_area_id()).collect(Collectors.groupingBy(WorkOrderInstallDetailPoint::getBuilding_area_id));
        Map<Long, List<WorkerDTO>> workersMap = workers.stream().filter(mp -> null != mp.getBuilding_area_id()).collect(Collectors.groupingBy(WorkerDTO::getBuilding_area_id));
        if (CollectionUtils.isNotEmpty(workOrderBuidingDetailVOS)) {
            Map<Integer, List<WorkOrderBuidingDetailVO>> buildingListMap = workOrderBuidingDetailVOS.stream().filter(mp -> null != mp.getBuilding_area_id()).collect(Collectors.groupingBy(WorkOrderBuidingDetailVO::getBuilding_area_id));
            if (buildingListMap != null && buildingListMap.keySet() != null && buildingListMap.size() != 0) {
                for (Integer building_area_id : buildingListMap.keySet()) {
                    WorkOrderBuidingDetailVO workOrderBuidingDetailVO = new WorkOrderBuidingDetailVO();
                    List<WorkOrderBuidingDetailVO> workOrderBuidingDetailVOS1 = buildingListMap.get(building_area_id);
                    workOrderBuidingDetailVO.setId(building_area_id.longValue());
                    workOrderBuidingDetailVO.setName(workOrderBuidingDetailVOS1.get(0).getName());
                    List<WorkOrderMediaPointVO> media_point = new ArrayList<>();
                    //新安装点位信息
                    Map<Integer, List<WorkOrderBuidingDetailVO>> newInstallPonitListMap = workOrderBuidingDetailVOS1.stream().filter(mp -> null != mp.getMedia_type_id()).collect(Collectors.groupingBy(WorkOrderBuidingDetailVO::getMedia_type_id));
                    if (InstallTypeEnum.INSTALL.getInstallType().equals(work_order_type_id) && newInstallPonitListMap != null && newInstallPonitListMap.keySet() != null && newInstallPonitListMap.size() != 0) {
                        for (Integer media_type_id : newInstallPonitListMap.keySet()) {
                            WorkOrderBuidingDetailVO new_workOrderBuidingDetailVO = newInstallPonitListMap.get(media_type_id).get(0);
                            Integer num = new_workOrderBuidingDetailVO.getNum();
                            String media_type_name = new_workOrderBuidingDetailVO.getMedia_type_name();
                            WorkOrderMediaPointVO pointVO = new WorkOrderMediaPointVO();
                            pointVO.setMedia_type_id(media_type_id);
                            pointVO.setName(media_type_name);
                            pointVO.setNum(num);
                            media_point.add(pointVO);
                        }
                    }
                    //巡检点位信息
                    if (InstallTypeEnum.CHECK.getInstallType().equals(work_order_type_id) && buildingPointListMap != null && buildingPointListMap.keySet() != null && buildingPointListMap.size() != 0) {
                        List<WorkOrderInstallDetailPoint> workOrderInstallDetailPointList1 = buildingPointListMap.get(building_area_id);
                        Map<Integer, List<WorkOrderInstallDetailPoint>> checkPonitListMap = workOrderInstallDetailPointList1.stream().filter(mp -> null != mp.getMedia_type_id()).collect(Collectors.groupingBy(WorkOrderInstallDetailPoint::getMedia_type_id));
                        if (checkPonitListMap != null && checkPonitListMap.keySet() != null && checkPonitListMap.size() != 0) {
                            for (Integer media_type_id : checkPonitListMap.keySet()) {
                                List<WorkOrderInstallDetailPoint> pointList = checkPonitListMap.get(media_type_id);
                                List<Long> point_ids = new ArrayList<>();
                                if (CollectionUtils.isNotEmpty(pointList)) {
                                    for (WorkOrderInstallDetailPoint point : pointList) {
                                        point_ids.add(point.getMedia_point_id().longValue());
                                    }
                                }
                                List<MediaType> mediaTypes1 = mediaTypesMap.get(media_type_id.longValue());
                                WorkOrderMediaPointVO pointVO = new WorkOrderMediaPointVO();
                                pointVO.setMedia_type_id(media_type_id);
                                pointVO.setName(mediaTypes1.get(0).getName());
                                pointVO.setPoint_ids(point_ids);
                                media_point.add(pointVO);
                            }
                        }
                    }
                    workOrderBuidingDetailVO.setMedia_point(media_point);
                    //工人信息
                    List<WorkerVO> buildingWorkers = new ArrayList<>();
                    if (workersMap != null && workersMap.keySet() != null && workersMap.size() != 0) {
                        List<WorkerDTO> workerDTOList = workersMap.get(building_area_id.longValue());
                        if (CollectionUtils.isNotEmpty(workerDTOList)) {
                            for (WorkerDTO workerDTO : workerDTOList) {
                                WorkerVO workerVO = new WorkerVO();
                                BeanUtils.copyProperties(workerDTO, workerVO);
                                buildingWorkers.add(workerVO);
                            }
                        }
                    }

                    //保存工人信息至销售单配置展示
                    if (CollectionUtils.isNotEmpty(pointProcessDateRangeVOList)) {
                        for (PointProcessDateRangeVO pointProcessDateRangeVO : pointProcessDateRangeVOList) {
                            List<BuildingPointVO> buildingPointVOList = pointProcessDateRangeVO.getBuildingPointVOList();
                            if (CollectionUtils.isNotEmpty(buildingPointVOList)) {
                                for (BuildingPointVO buildingPointVO : buildingPointVOList) {
                                    if (building_area_id.longValue() == (buildingPointVO.getId().longValue())) {
                                        buildingPointVO.setWorkers(buildingWorkers);
                                    }
                                }
                            }
                        }
                    }
                    workOrderBuidingDetailVO.setWorkers(buildingWorkers);
                    buidingDetailVOS.add(workOrderBuidingDetailVO);
                }
            }
        }
        workOrderDetailVO.setBuidingDetailVOS(buidingDetailVOS);
        return workOrderDetailVO;
    }

    @Override
    public Map<Integer, Integer> listWorkOrderNumOfType() {
        Map<Integer, Integer> result = new HashMap<>();
        List<WorkOrder> workOrders = baseMapper.selectListWorkOrderNumOfType();
        Map<Integer, List<WorkOrder>> WorkOrdersMap = workOrders.stream().filter(mp -> null != mp.getWork_order_type_id()).collect(Collectors.groupingBy(WorkOrder::getWork_order_type_id));
        Integer newInstallOrderNum = 0;
        Integer publishOrderNum = 0;
        Integer unPublishOrderNum = 0;
        Integer checkOrderNum = 0;
        Integer repairOrderNum = 0;
        int replaceOrderNum = 0;
        int monitoringNum = 0;
        if (WorkOrdersMap.containsKey(InstallTypeEnum.INSTALL.getInstallType())) {
            List<WorkOrder> newInstallOrders = WorkOrdersMap.get(InstallTypeEnum.INSTALL.getInstallType());
            if (CollectionUtils.isNotEmpty(newInstallOrders)) {
                newInstallOrderNum = newInstallOrders.size();
            }
        }
        if (WorkOrdersMap.containsKey(InstallTypeEnum.PUBLISH.getInstallType())) {
            List<WorkOrder> orders = WorkOrdersMap.get(InstallTypeEnum.PUBLISH.getInstallType());
            if (CollectionUtils.isNotEmpty(orders)) {
                publishOrderNum = orders.size();
            }
        }
        if (WorkOrdersMap.containsKey(InstallTypeEnum.UNPUBLISH.getInstallType())) {
            List<WorkOrder> orders = WorkOrdersMap.get(InstallTypeEnum.UNPUBLISH.getInstallType());
            if (CollectionUtils.isNotEmpty(orders)) {
                unPublishOrderNum = orders.size();
            }
        }
        if (WorkOrdersMap.containsKey(InstallTypeEnum.CHECK.getInstallType())) {
            List<WorkOrder> orders = WorkOrdersMap.get(InstallTypeEnum.CHECK.getInstallType());
            if (CollectionUtils.isNotEmpty(orders)) {
                checkOrderNum = orders.size();
            }
        }
        if (WorkOrdersMap.containsKey(InstallTypeEnum.REPLACE.getInstallType())) {
            List<WorkOrder> replaceOrders = WorkOrdersMap.get(InstallTypeEnum.REPLACE.getInstallType());
            if (CollectionUtils.isNotEmpty(replaceOrders)) {
                replaceOrderNum = replaceOrders.size();
            }
        }
        if (WorkOrdersMap.containsKey(InstallTypeEnum.INTERMEDIATE_MONITORING.getInstallType())) {
            List<WorkOrder> replaceOrders = WorkOrdersMap.get(InstallTypeEnum.INTERMEDIATE_MONITORING.getInstallType());
            if (CollectionUtils.isNotEmpty(replaceOrders)) {
                monitoringNum = replaceOrders.size();
            }
        }
        List<WorkOrder> repairOrders = baseMapper.listWorkOrderNumOfRepair();
        if (CollectionUtils.isNotEmpty(repairOrders)) {
            repairOrderNum = repairOrders.size();
        }
        result.put(InstallTypeEnum.INSTALL.getInstallType(), newInstallOrderNum);
        result.put(InstallTypeEnum.PUBLISH.getInstallType(), publishOrderNum);
        result.put(InstallTypeEnum.UNPUBLISH.getInstallType(), unPublishOrderNum);
        result.put(InstallTypeEnum.CHECK.getInstallType(), checkOrderNum);
        result.put(InstallTypeEnum.REPAIR.getInstallType(), repairOrderNum);
        result.put(InstallTypeEnum.REPLACE.getInstallType(), replaceOrderNum);
        result.put(InstallTypeEnum.INTERMEDIATE_MONITORING.getInstallType(), monitoringNum);
        return result;
    }

    @Override
    public Map<String, Integer> getAllWorkOrderProgressByTypeId(Long workOrderTypeId) {
        return baseMapper.getAllWorkOrderProgressByTypeId(workOrderTypeId);
    }

    @Override
    public List<WorkOrderProcessOfBuildingVO> listProcessOfBuilding(Long work_order_id, String name, Integer work_order_type_id) {
        List<WorkOrderProcessOfBuildingVO> list = baseMapper.listProcessOfBuilding(work_order_id, name);
        if (CollectionUtils.isNotEmpty(list)) {
            for (WorkOrderProcessOfBuildingVO workOrderProcessOfBuildingVO : list) {
                workOrderProcessOfBuildingVO.setWork_order_type_id(work_order_type_id);
            }
        }
        return list;
    }

    @Override
    public Page<SubmissionDetailVO> getWorkOrderSubmissionByBuildingId(Integer current_page, Integer page_size, Long work_order_id, Long building_id, String code, Boolean is_submit) {
        Page<SubmissionDetailVO> page = new Page<>(current_page, page_size);
        WorkOrder order = this.getById(work_order_id);
        if (is_submit) {
            if (order.getWork_order_type_id().equals(InstallTypeEnum.INSTALL.getInstallType())) {
                page.setRecords(baseMapper.getWorkOrderSubmitted(page, work_order_id, building_id, code));
            } else {
                page.setRecords(baseMapper.getWorkOrderSubmitted(page, work_order_id, building_id, code));
            }
        } else {
            if (order.getBill_sale_id() == null) {
                page.setRecords(baseMapper.getWorkOrderNotSubmittedByBuildingRelevant(page, work_order_id, building_id, code));
            } else {
                page.setRecords(baseMapper.getWorkOrderNotSubmittedBySaleOrderRelevant(page, work_order_id, building_id, code));
            }
        }
        return page;
    }

    @Override
    public void invalidByChooseIds(List<Long> chooseIdList) {
        baseMapper.updateMode(chooseIdList, 2);
    }

    @Override
    public void hangUpByChooseIds(List<Long> chooseIdList) {
        baseMapper.updateMode(chooseIdList, 1);
    }

    @Override
    public void cancelHangUpByChooseIds(List<Long> chooseIdList) {
        baseMapper.updateMode(chooseIdList, 0);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public boolean batchReplacePoint(WebBatchReplacePointDTO dto) {
        if (dto.getNew_device_ids().size() != dto.getOld_device_ids().size()) {
            throw new CommonException("需要替换的点位和替换的点位数量总和不对等");
        }
        boolean flag = true;
        AppReplacePointDTO replacePointDTO = new AppReplacePointDTO();
        replacePointDTO.setWork_order_id(dto.getWork_order_id());
        for (int i = 0; i < dto.getOld_device_ids().size(); i++) {
            replacePointDTO.setOld_device_id(dto.getOld_device_ids().get(i));
            replacePointDTO.setNew_device_id(dto.getNew_device_ids().get(i));
            flag = flag && this.replacePoint(replacePointDTO);
        }
        return flag;
    }

    @Override
    public void createImgPackage(Long work_order_id) {
        //修改工单生成压缩包状态
        baseMapper.update(null, Wrappers.<WorkOrder>lambdaUpdate().set(WorkOrder::getImg_zip_can_download, 0).set(WorkOrder::getImg_zip_path, null).eq(WorkOrder::getId, work_order_id));
        List<WorkerSubmit> list = workerSubmitService.list(Wrappers.<WorkerSubmit>lambdaQuery().eq(WorkerSubmit::getWork_order_id, work_order_id).eq(WorkerSubmit::getFlow_status, 4).isNull(WorkerSubmit::getDeleted_at));
        //获取所有的设备信息
        String tempPath = FILE_SPACE + File.separator + deviceImgTemPath;
        File temp = new File(tempPath);
        if (!temp.exists() && temp.isDirectory()) {
            temp.mkdirs();
        }
//        for (WorkerSubmit audit : list) {
//            List<LightboxImg> imglist = lightboxImgMapper.getList(audit.getId());
//            VDeviceDetailVO device = lightboxDeviceService.getDeviceDateilVO(tenantName, audit.getLightbox_id());
//            List<PictorialOriginImage> orginImages = pictorialOriginImageMapper.selectList(Wrappers.<PictorialOriginImage>lambdaQuery().eq(PictorialOriginImage::getWork_order_id, workOrderId));
//            //循环获取图片并保存到本地文件
//            for (int i = 0; i < imglist.size(); i++) {
//                String suffix = imglist.get(i).getUrl().substring(imglist.get(i).getUrl().lastIndexOf("."), imglist.get(i).getUrl().length());
//                File file = null;
//                String dirName = imglist.get(i).getBuilding_name();
//                if (dirName != null && !dirName.equals("")) {
//                    File dir = new File(tempPath + File.separator + dirName);
//                    if (!dir.exists()) {
//                        dir.mkdirs();
//                    }
//                }
//                if (imglist.size() > 1) {
//                    file = new File(tempPath + File.separator + (dirName != null && !dirName.equals("") ? dirName : "") + File.separator + device.getDetail2() + "(" + (i + 1) + ")" + suffix);
//                } else {
//                    file = new File(tempPath + File.separator + (dirName != null && !dirName.equals("") ? dirName : "") + File.separator + device.getDetail2() + suffix);
//                }
//                FileOutputStream fos = null;
//                try {
//                    if (!file.exists()) {
//                        file.getParentFile().mkdirs();
//                        file.createNewFile();
//                    }
//                    fos = new FileOutputStream(file);
//                    String filename = imglist.get(i).getUrl().split("/")[imglist.get(i).getUrl().split("/").length - 1];
//                    byte[] bytes = getFileBytes(imglist.get(i).getUrl());
//                    fos.write(bytes);
//                    fos.flush();
//                } catch (Exception e) {
//                    e.printStackTrace();
//                } finally {
//                    try {
//                        fos.close();
//                    } catch (Exception e2) {
//
//                    }
//                }
//            }
//            //循环保存设备原图
//            for (int i = 0; i < orginImages.size(); i++) {
//                String suffix = orginImages.get(i).getOrigin_image().substring(orginImages.get(i).getOrigin_image().lastIndexOf("."), orginImages.get(i).getOrigin_image().length());
//                File file = null;
//                if (orginImages.size() > 1) {
//                    file = new File(tempPath + File.separator + "原图(" + (i + 1) + ")" + suffix);
//                } else {
//                    file = new File(tempPath + File.separator + "原图" + suffix);
//                }
//                FileOutputStream fos = null;
//                try {
//                    if (!file.exists()) {
//                        file.getParentFile().mkdirs();
//                        file.createNewFile();
//                    }
//                    fos = new FileOutputStream(file);
//                    String filename = orginImages.get(i).getOrigin_image().split("/")[orginImages.get(i).getOrigin_image().split("/").length - 1];
//                    byte[] bytes = getFileBytes(orginImages.get(i).getOrigin_image());
//                    fos.write(bytes);
//                    fos.flush();
//                } catch (Exception e) {
//                    e.printStackTrace();
//                } finally {
//                    try {
//                        if (fos != null)
//                            fos.close();
//                    } catch (Exception e2) {
//
//                    }
//                }
//            }
//        }
        // 获取提交记录的ID集合
        Map<Long, List<WorkerSubmitPhotoVO>> map = null;
        try {
            List<Long> ids = list.stream().map(WorkerSubmit::getId).collect(Collectors.toList());
            // 获取图片数据
            List<WorkerSubmitPhotoVO> photos = workOrderSubmitPhotoService.listByWorkerSubmitIdsList(ids);
            map = photos.stream().filter(item -> item.getBuilding_area_id() != null).collect(Collectors.groupingBy(WorkerSubmitPhotoVO::getBuilding_area_id));
        } catch (Exception e) {
            baseMapper.update(null, Wrappers.<WorkOrder>lambdaUpdate().set(WorkOrder::getImg_zip_can_download, 2).set(WorkOrder::getImg_zip_path, null).eq(WorkOrder::getId, work_order_id));
            throw new RuntimeException("图片查询失败");
        }

        // 循环生成文件 保存在本地
        map.forEach((key, value) -> {
            for (int i = 0; i < value.size(); i++) {
                WorkerSubmitPhotoVO vo = value.get(i);
                String suffix = vo.getUrl().substring(vo.getUrl().lastIndexOf("."));
                File file = null;
                String dirName = vo.getBuilding_area_name();
                if (dirName != null && !dirName.equals("")) {
                    File dir = new File(tempPath + File.separator + dirName);
                    if (!dir.exists()) {
                        dir.mkdirs();
                    }
                }
                Map<String, List<WorkerSubmitPhotoVO>> collect = value.stream().collect(Collectors.groupingBy(WorkerSubmitPhotoVO::getCode));
                List<WorkerSubmitPhotoVO> devicePhotoList = collect.getOrDefault(vo.getCode(), new ArrayList<>());
                if (devicePhotoList.size() > 1) {
                    file = new File(tempPath + File.separator + (dirName != null && !dirName.equals("") ? dirName : "") + File.separator + vo.getCode() + "(" + (i + 1) + ")" + suffix);
                } else {
                    file = new File(tempPath + File.separator + (dirName != null && !dirName.equals("") ? dirName : "") + File.separator + vo.getCode() + suffix);
                }
                FileOutputStream fos = null;
                try {
                    if (!file.exists()) {
                        file.getParentFile().mkdirs();
                        file.createNewFile();
                    }
                    fos = new FileOutputStream(file);
                    byte[] bytes = getFileBytes(vo.getUrl());
                    if(bytes != null && bytes.length > 0) {
                        fos.write(bytes);
                    }
                    fos.flush();
                } catch (Exception e) {
                    baseMapper.update(null, Wrappers.<WorkOrder>lambdaUpdate().set(WorkOrder::getImg_zip_can_download, 2).set(WorkOrder::getImg_zip_path, null).eq(WorkOrder::getId, work_order_id));
                    throw new RuntimeException("图片下载失败");
                } finally {
                    try {
                        fos.close();
                    } catch (Exception e2) {

                    }
                }
            }
        });
        ZipOutputStream zos = null;
        File file = new File(tempPath);
        File zip = new File(FILE_SPACE + File.separator + "tmp.zip");
        try {
            FileOutputStream out = new FileOutputStream(zip);
            zos = new ZipOutputStream(out);
            compress(zos, file, "");
            out.flush();
            zos.close();
            out.close();
            //上传阿里云oss
            FileInputStream is = new FileInputStream(zip);
            MultipartFile multipartFile = new MockMultipartFile("file", zip.getName(), "application/x-zip-compressed", IOUtils.toByteArray(is));
            String s = attachmentService.store2("master", multipartFile.getInputStream(), multipartFile.getSize(), multipartFile.getContentType(), zip.getName());
            baseMapper.update(null, Wrappers.<WorkOrder>lambdaUpdate().set(WorkOrder::getImg_zip_can_download, 1).set(WorkOrder::getImg_zip_path, s).eq(WorkOrder::getId, work_order_id));
            is.close();
        } catch (IOException e) {
            baseMapper.update(null, Wrappers.<WorkOrder>lambdaUpdate().set(WorkOrder::getImg_zip_can_download, 2).set(WorkOrder::getImg_zip_path, null).eq(WorkOrder::getId, work_order_id));
            throw new RuntimeException("图片包生成失败");
        } finally {
            //临时存放的tmp压缩包删除
            zip.delete();
            //删除临时存放在文件夹下的图片
            clearTmpImage(new File(tempPath));
            try {
                if (zos != null) {
                    zos.close();
                }
            } catch (IOException e) {
                e.printStackTrace();
            }
        }

    }

    private void exportPointDetailByList(
            List<WorkOrderPointDetailVO> list,
            List<WorkOrderPointDetailVO> count,
            String name,
            HttpServletResponse response){
        // 创建表格对象
        HSSFWorkbook wb = new HSSFWorkbook();

        HSSFFont fontTitle = wb.createFont();
        fontTitle.setFontName("微软雅黑");
        fontTitle.setFontHeightInPoints((short) 18);//设置字体大小

        HSSFFont fontTableHead = wb.createFont();
        fontTableHead.setFontName("微软雅黑");
        fontTableHead.setFontHeightInPoints((short) 14);//设置字体大小

        HSSFFont fontCommon = wb.createFont();
        fontCommon.setFontName("微软雅黑");
        fontCommon.setFontHeightInPoints((short) 11);//设置字体大小

        // 创建标题样式
        HSSFCellStyle titleTextCellStyle = wb.createCellStyle();
        titleTextCellStyle.setWrapText(true);
        titleTextCellStyle.setAlignment(HorizontalAlignment.CENTER);
        titleTextCellStyle.setVerticalAlignment(VerticalAlignment.CENTER);
        titleTextCellStyle.setFont(fontTitle);
        // 创建表头样式
        HSSFCellStyle headTextCellStyle = wb.createCellStyle();
        headTextCellStyle.setWrapText(true);
        headTextCellStyle.setAlignment(HorizontalAlignment.CENTER);
        headTextCellStyle.setVerticalAlignment(VerticalAlignment.CENTER);
        headTextCellStyle.setFont(fontTableHead);
        headTextCellStyle.setFillForegroundColor(IndexedColors.LIGHT_BLUE.getIndex());

        // 创建换行样式
        HSSFCellStyle warpTextCellStyle = wb.createCellStyle();
        warpTextCellStyle.setWrapText(true);
        warpTextCellStyle.setAlignment(HorizontalAlignment.CENTER);
        warpTextCellStyle.setVerticalAlignment(VerticalAlignment.CENTER);
        // 创建居中样式
        HSSFCellStyle textCenterCellStyle = wb.createCellStyle();
        textCenterCellStyle.setAlignment(HorizontalAlignment.CENTER);
        textCenterCellStyle.setVerticalAlignment(VerticalAlignment.CENTER);
        textCenterCellStyle.setFont(fontCommon);
        // 创建sheet
        HSSFSheet sheet = wb.createSheet();
        // 创建表头
        HSSFRow firstRow = sheet.createRow(0);
        HSSFCell firstRowCell = firstRow.createCell(0);
        firstRowCell.setCellValue(name + "资源详细点位表");
        firstRowCell.setCellStyle(titleTextCellStyle);
        HSSFRow row = sheet.createRow(1);
        HSSFCell cell = row.createCell(0);
        cell.setCellValue("序号");
        cell.setCellStyle(headTextCellStyle);

        HSSFCell cell1 = row.createCell(1);
        cell1.setCellValue("行政区域");
        cell1.setCellStyle(headTextCellStyle);
        HSSFCell cell2 = row.createCell(2);
        cell2.setCellValue("项目名称");
        cell2.setCellStyle(headTextCellStyle);
        HSSFCell cell3 = row.createCell(3);
        cell3.setCellValue("媒体类型");
        cell3.setCellStyle(headTextCellStyle);
        HSSFCell cell4 = row.createCell(4);
        cell4.setCellValue("设备编号");
        cell4.setCellStyle(headTextCellStyle);
        HSSFCell cell5 = row.createCell(5);
        cell5.setCellValue("地址");
        cell5.setCellStyle(headTextCellStyle);
        HSSFCell cell6 = row.createCell(6);
        cell6.setCellValue("楼栋");
        cell6.setCellStyle(headTextCellStyle);
        HSSFCell cell7 = row.createCell(7);
        cell7.setCellValue("单元");
        cell7.setCellStyle(headTextCellStyle);
        HSSFCell cell8 = row.createCell(8);
        cell8.setCellValue("楼层");
        cell8.setCellStyle(headTextCellStyle);
        HSSFCell cell9 = row.createCell(9);
        cell9.setCellValue("合计");
        cell9.setCellStyle(headTextCellStyle);
        HSSFCell cell10 = row.createCell(10);
        cell10.setCellValue("尺寸(cm)");
        cell10.setCellStyle(headTextCellStyle);
        HSSFCell cell11 = row.createCell(11);
        cell11.setCellValue("材质");
        cell11.setCellStyle(headTextCellStyle);

        sheet.setColumnWidth(0, 200 * 10);
        sheet.setColumnWidth(1, 200 * 40);
        sheet.setColumnWidth(2, 200 * 20);
        sheet.setColumnWidth(3, 200 * 20);
        sheet.setColumnWidth(4, 200 * 20);
        sheet.setColumnWidth(5, 200 * 70);
        sheet.setColumnWidth(6, 200 * 10);
        sheet.setColumnWidth(7, 200 * 10);
        sheet.setColumnWidth(8, 200 * 10);
        sheet.setColumnWidth(9, 200 * 10);
        sheet.setColumnWidth(10, 200 * 20);
        sheet.setColumnWidth(11, 200 * 30);

        sheet.addMergedRegion(new CellRangeAddress(0, 0, 0, 11));

        Map<Long, Integer> countMap = count.stream().collect(Collectors.toMap(WorkOrderPointDetailVO::getMedia_type_id, WorkOrderPointDetailVO::getCount))
                .entrySet()
                .stream()
                .sorted(Map.Entry.comparingByKey())
                .collect(Collectors.toMap(Map.Entry::getKey, Map.Entry::getValue,
                        (oldValue, newValue) -> oldValue, LinkedHashMap::new));

        if (list != null && list.size() > 0) {
            int index = 2;

            for (WorkOrderPointDetailVO vo2 : list) {
                Integer co = countMap.getOrDefault(vo2.getMedia_type_id(), 0);
                vo2.setCount(co);
            }

            for (int i = 0; i < list.size(); i++) {
                fillExcel(list.get(i), index, sheet, textCenterCellStyle);
                index++;
            }

            int index2 = 2;
            for (Integer co : countMap.values()) {
                sheet.addMergedRegion(new CellRangeAddress(index2, index2 + co - 1, 9, 9));
                index2 += co;
            }
        }

        try {
            response.setContentType("application/msexcel");
            response.setHeader("Content-Disposition", "attachment;filename=" + URLEncoder.encode("详细点位导出.xlsx", "UTF-8"));
            OutputStream out = response.getOutputStream();
            wb.write(out);
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    @Override
    public void exportLockPointDetail(Long lockId, String name, HttpServletResponse response) {
        List<WorkOrderPointDetailVO> list = baseMapper.getPointDetailListByLockId(lockId);
        List<WorkOrderPointDetailVO> count = new ArrayList<>();
        if(CollectionUtils.isNotEmpty(list)) count = baseMapper.getPointDetailListCountByLockId(lockId);
        exportPointDetailByList(list, count, name, response);
    }

    @Override
    public void exportWorkOrderPointDetail(Long id, String name, HttpServletResponse response) {
        List<WorkOrderPointDetailVO> list = baseMapper.getWorkOrderPointDetailList(id);
        List<WorkOrderPointDetailVO> count = new ArrayList<>();
        if(CollectionUtils.isNotEmpty(list)) count = baseMapper.getCount(id);
        exportPointDetailByList(list, count, name, response);
    }

    /**
     * 清除图片的方法
     */
    private void clearTmpImage(File file) {
        if (file.isDirectory()) {//如果是文件夹
            File[] files = file.listFiles();//获取所有文件
            if (files.length == 0) {//如果是空文件夹则删除自身
                file.delete();
                return;
            } else {//不是空文件夹则递归删除
                for (File f : files) {
                    clearTmpImage(f);
                }
                //所有文件删除完了以后删除自身
                file.delete();
                return;
            }
        } else {//如果不是文件夹
            file.delete();
            return;
        }
    }

    public byte[] getFileBytes(String filePath) {
        int maxTryTime = 5; //重试次数
        int curTryTime = 1; //当前次
        byte[] bytes = null;
        while (bytes == null && curTryTime <= maxTryTime){
            try{
                if(curTryTime > 1) Thread.sleep(3000); // 非第一次请求，睡眠3秒
            }catch (Exception ignore){}

            log.info("开始获取图片:" + filePath);

            try {
                bytes = queryFileBytes(filePath);
            }catch (Exception e) {
                log.error("第"+curTryTime+"次下载图片失败："+filePath, e);
            }

            curTryTime++;
        }
        return bytes;
    }

    private byte[] queryFileBytes(String filePath) throws IOException {
        int HttpResult; // 服务器返回的状态
        byte[] bytes = null;
        URL url = new URL(filePath); // 创建URL
        URLConnection urlconn = url.openConnection(); // 试图连接并取得返回状态码
        urlconn.connect();
        HttpURLConnection httpconn = (HttpURLConnection) urlconn;
        HttpResult = httpconn.getResponseCode();
        if (HttpResult != HttpURLConnection.HTTP_OK) {
            log.error("无法连接到服务器");
            //throw new RuntimeException("无法连接到服务器");
        } else {
            int filesize = urlconn.getContentLength(); // 取数据长度
            System.out.println("取数据长度====" + filesize);
            urlconn.getInputStream();
            InputStream inputStream = urlconn.getInputStream();

            ByteArrayOutputStream swapStream = new ByteArrayOutputStream();
            int ch;
            while ((ch = inputStream.read()) != -1) {
                swapStream.write(ch);
            }
            bytes = swapStream.toByteArray();
        }
        if(bytes != null) log.info("文件大小====" + bytes.length);
        return bytes;
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public Boolean assignWorkers(WorkOrderAssignWorkersDTO workOrderAssignWorkersDTO) {
        // 删除工单下所有的工人和楼盘信息
        workOrderInstallDetailWorkerMapper.delete(Wrappers.<WorkOrderInstallDetailWorker>lambdaQuery().eq(WorkOrderInstallDetailWorker::getWork_order_id, workOrderAssignWorkersDTO.getId()));
        // 查询出工单下所有的detail信息
        List<WorkOrderInstallDetail> list = workOrderInstallDetailService.list(Wrappers.<WorkOrderInstallDetail>lambdaQuery().eq(WorkOrderInstallDetail::getWork_order_id, workOrderAssignWorkersDTO.getId()));
        //  保存新的数据
        List<WorkOrderInstallDetailWorker> data = new ArrayList<>();
        list.forEach(item -> {
            long building_area_id = item.getBuilding_area_id().longValue();
            if (workOrderAssignWorkersDTO.getWork_order_building_worker_ids().containsKey(building_area_id)) {
                List<Long> worker_ids = workOrderAssignWorkersDTO.getWork_order_building_worker_ids().get(building_area_id);
                for (Long worker_id : worker_ids) {
                    WorkOrderInstallDetailWorker workOrderInstallDetailWorker = new WorkOrderInstallDetailWorker();
                    workOrderInstallDetailWorker.setWork_order_id(workOrderAssignWorkersDTO.getId().intValue());
                    workOrderInstallDetailWorker.setWork_order_install_detail_id(item.getId().intValue());
                    workOrderInstallDetailWorker.setWorker_id(worker_id.intValue());
                    workOrderInstallDetailWorker.setBuilding_area_id(item.getBuilding_area_id());
                    data.add(workOrderInstallDetailWorker);
                }
            }
        });
        return workOrderInstallDetailWorkerService.saveBatch(data);
    }
}
